home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 152 / doodle2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-21  |  59.0 KB  |  1,742 lines

  1. /************************************************************************/
  2. /*      File:   doodle.c                                                */
  3. /************************************************************************/
  4. /* ATARI ADAPTATION IN COLOR BY HARRY KOONS    VERSION 1.1B    7/11/85  */
  5. /*      includes         ****************************************       */
  6. #include <osbind.h>                             /* gemdos bindings      */
  7. #include <obdefs.h>                             /* object definitions   */
  8. #include <gemdefs.h>                            /* misc gem definitions */
  9. #include <vdibind.h>                            /* vdi binding structs  */
  10. #include <vdibind.h>                            /* vdi binding structs  */
  11. #include <portab.h>                             /* portable coding conv */
  12. /* #include "machine.h" i.e. pick what works!      machine dependent    */
  13. #include <define.h>                             /* misc. definitions    */
  14. #include <taddr.h>                              /* tree address macros  */
  15. #include <doodle2.h>               /* doodle2-RCS-application resource  */
  16. /*      defines      ****************************************           */
  17. #define DESK            0
  18.  
  19. #define END_UPDATE      0
  20. #define BEG_UPDATE      1
  21.  
  22. #define SHADE0          0
  23. #define SHADE1          1
  24. #define SHADE2          2
  25. #define SHADE3          3
  26. #define SHADE4          4
  27. #define SHADE5          5
  28. #define SHADE6          6
  29. #define SHADE7          7
  30. #define SHADE8          8
  31. #define SHADE9          9
  32. #define SHADE10         10
  33. #define SHADE11         11
  34. #define SHADE12         12
  35. #define SHADE13         13
  36. #define SHADE14         14
  37. #define SHADE15         15
  38.  
  39.  
  40.  
  41. #define PEN_FINE        1
  42. #define PEN_MEDIUM      5
  43. #define PEN_BROAD       9
  44.  
  45.  
  46. #define WA_UPPAGE       0               /* arrow message        */
  47. #define WA_DNPAGE       1
  48. #define WA_UPLINE       2
  49. #define WA_DNLINE       3
  50. #define WA_LFPAGE       4
  51. #define WA_RTPAGE       5
  52. #define WA_LFLINE       6
  53. #define WA_RTLINE       7
  54.  
  55.  
  56. /*      Macros    **************************************              */
  57. #define LLGET(x) (*((LONG*)(x)))
  58. #define LLSET(x,y) (*((LONG*)(x))=y)
  59. #define LWGET(x) ((WORD)*((WORD*)(x)))
  60. #define LWSET(x,y) (*((WORD*)(x))=y)
  61. #define YSCALE(x) UMD(x, scrn_xsize, scrn_ysize)
  62. #define TE_TXTLEN(x) (x + 24)
  63. #define ADDR /**/
  64. #define GLOBAL /**/
  65. /****                       Data Structures                          ****/
  66. /*      Extrnl Data Structures  *****************************************/
  67. UWORD   dos_err;        /* no longer external  */
  68. /*      Global Data Structures  *****************************************/
  69.  
  70. GLOBAL WORD     contrl[11];             /* control inputs               */
  71. GLOBAL WORD     intin[80];              /* max string length            */
  72. GLOBAL WORD     ptsin[256];             /* polygon fill points          */
  73. GLOBAL WORD     intout[45];             /* open workstation output      */
  74. GLOBAL WORD     ptsout[12];
  75. /*      Local Data Structures   */
  76. WORD    gl_wchar;                       /* character width              */
  77. WORD    gl_hchar;                       /* character height             */
  78. WORD    gl_wbox;                        /* box (cell) width             */
  79. WORD    gl_hbox;                        /* box (cell) height            */
  80. WORD    gl_hspace;                      /* height of space between lines*/
  81. WORD    gem_handle;                     /* GEM vdi handle               */
  82. WORD    vdi_handle;                     /* doodle vdi handle            */
  83. WORD    work_out[57];                   /* open virt workstation values */
  84. GRECT   scrn_area;                      /* whole scrn area              */
  85. GRECT   work_area;                      /* drawing area of main window  */
  86. GRECT   undo_area;                      /* area equal to work_area      */
  87. GRECT   save_area;                      /* save area for full/unfulling */
  88. WORD    gl_rmsg[8];                     /* message buffer               */
  89. LONG    ad_rmsg;                        /* LONG pointer to message bfr  */
  90. LONG    gl_menu;                        /* menu tree address            */
  91. WORD    gl_apid;                        /* application ID               */
  92. WORD    gl_xfull;                       /* full window 'x'              */
  93. WORD    gl_yfull;                       /* full window 'y'              */
  94. WORD    gl_wfull;                       /* full window 'w'              */
  95. WORD    gl_hfull;                       /* full window 'h'              */
  96. WORD    scrn_width;                     /* scrn width in pixels */
  97. WORD    scrn_height;                    /* scrn height in pixels        */
  98. WORD    scrn_planes;                    /* number of color planes       */
  99. WORD    scrn_xsize;                     /* width of one pixel           */
  100. WORD    scrn_ysize;                     /* height of one pixel          */
  101. UWORD   m_out = FALSE;                  /* mouse in/out of window flag  */
  102. WORD    ev_which;                       /* event multi return state(s)  */
  103. UWORD   mousex, mousey;                 /* mouse x,y position           */
  104. UWORD   bstate, bclicks;                /* button state, & # of clicks  */
  105. UWORD   kstate, kreturn;                /* key state and keyboard char  */
  106. MFDB    undo_mfdb;                      /* undo buffer mmry frm def blk */
  107. MFDB    scrn_mfdb;                      /* scrn memory form defn blk    */
  108. LONG    buff_size;                      /* buffer size req'd for scrn   */
  109. LONG    buff_location;                  /* scrn buffer pointer          */
  110. WORD    dodle_whndl;                    /* doodle window handle         */
  111. BOOLEAN dood_fill = FALSE;              /* fill or draw flag            */
  112. BOOLEAN first_fill = FALSE;             /* to set background color      */
  113. WORD    dodle_shade = SHADE1;           /* doodle current pen shade     */
  114. WORD    pen_ink = SHADE1;               /* current ink shade            */
  115. WORD    bkgr_color = SHADE0;            /* current background shade     */
  116. WORD    bkgr_next = SHADE0;             /* next background shade        */
  117. WORD    dodle_pen = 1;                  /* doodle current pen width     */
  118. WORD    dodle_height = 4;               /* doodle current char height   */
  119. WORD    char_fine;                      /* character height for fine    */
  120. WORD    char_medium;                    /* character height for medium  */
  121. WORD    char_broad;                     /* character height for broad   */
  122. WORD    monumber = 5;                   /* mouse form number            */
  123. LONG    mofaddr = 0x0L;                 /* mouse form address           */
  124. WORD    file_handle;                    /* file handle -> pict ld/sv    */
  125. BYTE    file_name[64] = "";             /* current pict file name       */
  126. BOOLEAN key_input;                      /* key inputting state          */
  127. WORD    key_xbeg;                       /* x position for line beginning*/
  128. WORD    key_ybeg;                       /* y position for line beginning*/
  129. WORD    key_xcurr;                      /* current x position           */
  130. WORD    key_ycurr;                      /* current y position           */
  131.                                         /* doodle window title          */
  132. BYTE    *wdw_title = "  Doodle2  Window ";
  133. /*      Mouse Data Structures   */
  134. WORD    erase_broad[37] =               /* mouse form for broad eraser  */
  135. {
  136.         7, 7, 1, 0, 1,
  137.         0x0000, 0x0000, 0x0000, 0x0000, /* mask */
  138.         0x0000, 0x1ff0, 0x1ff0, 0x1ff0,
  139.         0x1ff0, 0x1ff0, 0x0000, 0x0000,
  140.         0x0000, 0x0000, 0x0000, 0x0000,
  141.         0x0000, 0x0000, 0x0000, 0x0000, /* data */
  142.         0x7ffc, 0x600c, 0x600c, 0x600c,
  143.         0x600c, 0x600c, 0x7ffc, 0x0000,
  144.         0x0000, 0x0000, 0x0000, 0x0000
  145. };
  146. WORD    erase_medium[37] =              /* mouse form for medium eraser */
  147. {
  148.         7, 7, 1, 0, 1,
  149.         0x0000, 0x0000, 0x0000, 0x0000, /* mask */
  150.         0x0000, 0x0000, 0x07c0, 0x07c0,
  151.         0x07c0, 0x0000, 0x0000, 0x0000,
  152.         0x0000, 0x0000, 0x0000, 0x0000,
  153.         0x0000, 0x0000, 0x0000, 0x0000, /* data */
  154.         0x0000, 0x1ff0, 0x1830, 0x1830,
  155.         0x1830, 0x1ff0, 0x0000, 0x0000,
  156.         0x0000, 0x0000, 0x0000, 0x0000
  157. };
  158. WORD    erase_fine[37] =                /* mouse form for fine eraser   */
  159. {
  160.         7, 7, 1, 0, 1,
  161.         0x0000, 0x0000, 0x0000, 0x0000, /* mask */
  162.         0x0000, 0x0000, 0x0000, 0x0100,
  163.         0x0000, 0x0000, 0x0000, 0x0000,
  164.         0x0000, 0x0000, 0x0000, 0x0000,
  165.         0x0000, 0x0000, 0x0000, 0x0000, /* data */
  166.         0x0000, 0x0000, 0x07c0, 0x06c0,
  167.         0x07c0, 0x0000, 0x0000, 0x0000,
  168.         0x0000, 0x0000, 0x0000, 0x0000
  169. };
  170. /****                       Local Procedures                         ****/
  171. /*      min                     */
  172. WORD    min(a, b)                       /* return min of two values */
  173. WORD            a, b;
  174. {
  175.         return( (a < b) ? a : b );
  176. }
  177. /*      max                     */
  178. WORD    max(a, b)                       /* return max of two values */
  179. WORD            a, b;
  180. {
  181.         return( (a > b) ? a : b );
  182. }
  183.  
  184.  
  185. /*------------------------------*/
  186. /*      string_addr             */
  187. /*------------------------------*/
  188. LONG
  189. string_addr(which)              /* returns a tedinfo LONG string addr   */
  190. WORD    which;
  191. {
  192.         LONG    where;
  193.  
  194.         rsrc_gaddr(R_STRING, which, &where);
  195.         return (where);
  196.  
  197.  
  198. /*------------------------------*/
  199. /*      rc_equal                */
  200. /*------------------------------*/
  201. WORD
  202. rc_equal(p1, p2)                /* tests for two rectangles equal       */
  203. GRECT           *p1, *p2;
  204. {
  205.         if ((p1->g_x != p2->g_x) ||
  206.             (p1->g_y != p2->g_y) ||
  207.             (p1->g_w != p2->g_w) ||
  208.             (p1->g_h != p2->g_h))
  209.                 return(FALSE);
  210.         return(TRUE);
  211. }
  212.  
  213.  
  214.  
  215. /*------------------------------*/
  216. /*      rc_copy                 */
  217. /*------------------------------*/
  218. VOID
  219. rc_copy(psbox, pdbox)           /* copy source to destination rectangle */
  220. GRECT   *psbox;
  221. GRECT   *pdbox;
  222. {
  223.         pdbox->g_x = psbox->g_x;
  224.         pdbox->g_y = psbox->g_y;
  225.         pdbox->g_w = psbox->g_w;
  226.         pdbox->g_h = psbox->g_h;
  227. }
  228.  
  229.  
  230. /*------------------------------*/
  231. /*      rc_intersect            */
  232. /*------------------------------*/
  233. WORD
  234. rc_intersect(p1, p2)            /* compute intersect of two rectangles  */
  235. GRECT           *p1, *p2;
  236. {
  237.         WORD            tx, ty, tw, th;
  238.  
  239.         tw = min(p2->g_x + p2->g_w, p1->g_x + p1->g_w);
  240.         th = min(p2->g_y + p2->g_h, p1->g_y + p1->g_h);
  241.         tx = max(p2->g_x, p1->g_x);
  242.         ty = max(p2->g_y, p1->g_y);
  243.         p2->g_x = tx;
  244.         p2->g_y = ty;
  245.         p2->g_w = tw - tx;
  246.         p2->g_h = th - ty;
  247.         return( (tw > tx) && (th > ty) );
  248. }
  249.  
  250.  
  251. /*------------------------------*/
  252. /*      inside                  */
  253. /*------------------------------*/
  254. UWORD
  255. inside(x, y, pt)                /* determine if x,y is in rectangle     */
  256. UWORD           x, y;
  257. GRECT           *pt;
  258. {
  259.         if ( (x >= pt->g_x) && (y >= pt->g_y) &&
  260.             (x < pt->g_x + pt->g_w) && (y < pt->g_y + pt->g_h) )
  261.                 return(TRUE);
  262.         else
  263.                 return(FALSE);
  264. } /* inside */
  265.  
  266.  
  267. /*------------------------------*/
  268. /*      grect_to_array          */
  269. /*------------------------------*/
  270. VOID
  271. grect_to_array(area, array)     /* convert x,y,w,h to upr lt x,y and    */
  272. GRECT   *area;                  /*                    lwr rt x,y        */
  273. WORD    *array;
  274. {
  275.         *array++ = area->g_x;
  276.         *array++ = area->g_y;
  277.         *array++ = area->g_x + area->g_w - 1;
  278.         *array = area->g_y + area->g_h - 1;
  279. }
  280.  
  281.  
  282. /*------------------------------*/
  283. /*      rast_op                 */
  284. /*------------------------------*/
  285. VOID
  286. rast_op(mode, s_area, s_mfdb, d_area, d_mfdb)   /* bit block level trns */
  287. WORD    mode;
  288. GRECT   *s_area, *d_area;
  289. MFDB    *s_mfdb, *d_mfdb;
  290. {
  291.         WORD    pxy[8];
  292.  
  293.         grect_to_array(s_area, pxy);
  294.         grect_to_array(d_area, &pxy[4]);
  295.         vro_cpyfm(vdi_handle, mode, pxy, s_mfdb, d_mfdb);
  296. }
  297.  
  298.  
  299. /*------------------------------*/
  300. /*      do_open                 */
  301. /*------------------------------*/
  302. VOID
  303. do_open(wh, org_x, org_y, x, y, w, h)   /* grow and open specified wdw  */
  304. WORD    wh;
  305. WORD    org_x, org_y;
  306. WORD    x, y, w, h;
  307. {
  308.         graf_growbox(org_x, org_y, 21, 21, x, y, w, h);
  309.         wind_open(wh, x, y, w, h);
  310. }
  311.  
  312.  
  313. /*------------------------------*/
  314. /*      do_close                */
  315. /*------------------------------*/
  316. VOID
  317. do_close(wh, org_x, org_y)      /* close and shrink specified window    */
  318. WORD    wh;
  319. WORD    org_x, org_y;
  320. {
  321.         WORD    x, y, w, h;
  322.  
  323.         wind_get(wh, WF_CURRXYWH, &x, &y, &w, &h);
  324.         wind_close(wh);
  325.         graf_shrinkbox(org_x, org_y, 21, 21, x, y, w, h);
  326. }
  327.  
  328.  
  329. /*------------------------------*/
  330. /*      hndl_dial               */
  331. /*------------------------------*/
  332. WORD
  333. hndl_dial(tree, def, x, y, w, h)        /* center, display and get input*/
  334. LONG    tree;                           /*   from specified dialogue box*/
  335. WORD    def;
  336. WORD    x, y, w, h;
  337. {
  338.         WORD    xdial, ydial, wdial, hdial;
  339.         WORD    exit_obj;
  340.  
  341.         form_center(tree, &xdial, &ydial, &wdial, &hdial);
  342.         form_dial(0, x, y, w, h, xdial, ydial, wdial, hdial);
  343.         form_dial(1, x, y, w, h, xdial, ydial, wdial, hdial);
  344.         objc_draw(tree, ROOT, MAX_DEPTH, xdial, ydial, wdial, hdial);
  345.         exit_obj = form_do(tree, def);
  346.         form_dial(2, x, y, w, h, xdial, ydial, wdial, hdial);
  347.         form_dial(3, x, y, w, h, xdial, ydial, wdial, hdial);
  348.         return (exit_obj);
  349. }
  350.  
  351.  
  352. /*------------------------------*/
  353. /*      set_clip                */
  354. /*------------------------------*/
  355. VOID
  356. set_clip(clip_flag, s_area)     /* set clip to specified area   */
  357. WORD    clip_flag;
  358. GRECT   *s_area;
  359. {
  360.         WORD    pxy[4];
  361.  
  362.         grect_to_array(s_area, pxy);
  363.         vs_clip(vdi_handle, clip_flag, pxy);
  364. }
  365.  
  366.  
  367. /*------------------------------*/
  368. /*      align_x                 */
  369. /*------------------------------*/
  370. WORD
  371. align_x(x)              /* forces word alignment for column position    */
  372. WORD    x;              /*   rounding to nearest word                   */
  373. {
  374.         /*      return((x & 0xfff0) + ((x & 0x000c) ? 0x0010 : 0));     IBM */
  375.         return(x);      /* ATARI        */      
  376. }       
  377.  
  378.  
  379. /*
  380.  
  381. Page*/
  382. /************************************************************************/
  383. /************************************************************************/
  384. /****                                                                ****/
  385. /****                       Work Area Management                     ****/
  386. /****                                                                ****/
  387. /************************************************************************/
  388. /************************************************************************/
  389.  
  390.  
  391. /*------------------------------*/
  392. /*      set_work                */
  393. /*------------------------------*/
  394. VOID
  395. set_work(slider_update)         /* update undo area, clamping to page   */
  396. BOOLEAN slider_update;          /*   edges, and updt sliders if req'd   */
  397. {
  398.         WORD    i;
  399.  
  400.         wind_get(dodle_whndl, WF_WORKXYWH,
  401.         &work_area.g_x, &work_area.g_y,
  402.         &work_area.g_w, &work_area.g_h);
  403.  
  404.         undo_area.g_w = work_area.g_w;
  405.         undo_area.g_h = work_area.g_h;
  406.         /**/                           /* clamp work area to page edges */
  407.         if ((i = undo_mfdb.fwp - (undo_area.g_x + undo_area.g_w)) < 0)
  408.                 undo_area.g_x += i;
  409.         if ((i = undo_mfdb.fh - (undo_area.g_y + undo_area.g_h)) < 0)
  410.                 undo_area.g_y += i;
  411.  
  412.         if (slider_update)
  413.         {
  414.                 wind_set(dodle_whndl, WF_HSLIDE, UMD(undo_area.g_x, 1000,
  415.                         undo_mfdb.fwp - undo_area.g_w), 0, 0, 0);
  416.                 wind_set(dodle_whndl, WF_VSLIDE, UMD(undo_area.g_y, 1000,
  417.                         undo_mfdb.fh - undo_area.g_h), 0, 0, 0);
  418.                 wind_set(dodle_whndl, WF_HSLSIZE,UMD(work_area.g_w, 1000,
  419.                         undo_mfdb.fwp), 0, 0, 0);
  420.                 wind_set(dodle_whndl, WF_VSLSIZE,UMD(work_area.g_h, 1000,
  421.                         undo_mfdb.fh), 0, 0, 0);
  422.         }
  423.  
  424.         undo_area.g_x = align_x(undo_area.g_x);
  425.         /* only use portion of work_area on scrn        */
  426.         rc_intersect(&scrn_area, &work_area);
  427.         undo_area.g_w = work_area.g_w;
  428.         undo_area.g_h = work_area.g_h;
  429. }
  430.  
  431.  
  432. /*------------------------------*/
  433. /*      save_work               */
  434. /*------------------------------*/
  435. VOID
  436. save_work()                     /* copy work_area to undo_area buffer   */
  437. {
  438.         GRECT   tmp_area;
  439.  
  440.         rc_copy(&work_area,&tmp_area);
  441.         rc_intersect(&scrn_area,&tmp_area);
  442.         graf_mouse(M_OFF, 0x0L);
  443.         rast_op(3, &tmp_area, &scrn_mfdb, &undo_area, &undo_mfdb);
  444.         graf_mouse(M_ON, 0x0L);
  445. }
  446.  
  447.  
  448. /*------------------------------*/
  449. /*      restore_work            */
  450. /*------------------------------*/
  451. VOID
  452. restore_work()                  /* restore work_area from undo_area     */
  453. {
  454.         GRECT   tmp_area;
  455.  
  456.         rc_copy(&work_area,&tmp_area);
  457.         rc_intersect(&scrn_area,&tmp_area);
  458.         graf_mouse(M_OFF, 0x0L);
  459.         rast_op(3, &undo_area, &undo_mfdb, &tmp_area, &scrn_mfdb);
  460.         graf_mouse(M_ON, 0x0L);
  461. }
  462.  
  463.  
  464. /*
  465.  
  466. Page*/
  467. /************************************************************************/
  468. /************************************************************************/
  469. /****                                                                ****/
  470. /****                       Object Tree Manipulation                 ****/
  471. /****                                                                ****/
  472. /************************************************************************/
  473. /************************************************************************/
  474.  
  475.  
  476. /*------------------------------*/
  477. /*      do_obj                  */
  478. /*------------------------------*/
  479. VOID
  480. do_obj(tree, which, bit)        /* set specified bit in object state    */
  481. LONG    tree;
  482. WORD    which, bit;
  483. {
  484.         WORD    state;
  485.  
  486.         state = LWGET(OB_STATE(which));
  487.         LWSET(OB_STATE(which), state | bit);
  488. }
  489.  
  490.  
  491. /*------------------------------*/
  492. /*      undo_obj                */
  493. /*------------------------------*/
  494. VOID
  495. undo_obj(tree, which, bit)      /* clear specified bit in object state  */
  496. LONG    tree;
  497. WORD    which, bit;
  498. {
  499.         WORD    state;
  500.  
  501.         state = LWGET(OB_STATE(which));
  502.         LWSET(OB_STATE(which), state & ~bit);
  503. }
  504.  
  505. /*------------------------------*/
  506. /*      sel_obj                 */
  507. /*------------------------------*/
  508. VOID
  509. sel_obj(tree, which)            /* turn on selected bit of spcfd object */
  510. LONG    tree;
  511. WORD    which;
  512. {
  513.         do_obj(tree, which, SELECTED);
  514. }
  515.  
  516.  
  517. /*------------------------------*/
  518. /*      desel_obj               */
  519. /*------------------------------*/
  520. VOID
  521. desel_obj(tree, which)          /* turn off selected bit of spcfd object*/
  522. LONG    tree;
  523. WORD    which;
  524. {
  525.         undo_obj(tree, which, SELECTED);
  526. }
  527.  
  528.  
  529. /*------------------------------*/
  530. /*      enab_menu               */
  531. /*------------------------------*/
  532. VOID
  533. enab_menu(which)                /* enable specified menu item   */
  534. WORD    which;
  535. {
  536.         undo_obj(gl_menu, which, DISABLED);
  537. }
  538.  
  539. /*------------------------------*/
  540. /*      objc_xywh               */
  541. /*------------------------------*/
  542. VOID
  543. objc_xywh(tree, obj, p)         /* get x,y,w,h for specified object     */
  544. LONG    tree;
  545. WORD    obj;
  546. GRECT   *p;
  547. {
  548.         objc_offset(tree, obj, &p->g_x, &p->g_y);
  549.         p->g_w = LWGET(OB_WIDTH(obj));
  550.         p->g_h = LWGET(OB_HEIGHT(obj));
  551. }
  552. /****                       File Path Name Functions                 ****/
  553. /*      dial_name   ****************************************            */
  554. WORD    dial_name ( name )              /* dialogue box input filename  */
  555. BYTE    *name;
  556. {                   
  557.        LONG    tree ;
  558.        LONG    ted_addr ;
  559.        BYTE    c ;
  560.        WORD    i, j;
  561.        GRECT   box;
  562.  
  563.  
  564.        objc_xywh(gl_menu, DOODFILE, &box);
  565.        rsrc_gaddr( R_TREE, DOODSVAD, &tree) ;
  566.        ted_addr = LLGET(OB_SPEC(DOODNAME));
  567.        LLSET( ted_addr, ADDR(name) ) ;
  568.        LWSET( TE_TXTLEN(ted_addr),8);
  569.        name[0] = '\0';
  570.        if(hndl_dial(tree,DOODNAME,box.g_x,box.g_y,box.g_w,box.g_h)==DOODSOK)
  571.        {
  572.                i =
  573.                    j =  0;
  574.                while (TRUE)
  575.                {
  576.                        c = name[i++];
  577.                        if (!c)
  578.                                break ;
  579.                        if ( (c != ' ') && (c != '_') )
  580.                                name[j++] = c ;
  581.                }
  582.                if ( *name )
  583.                        strcpy( &name[j], ".DOO" ) ;
  584.                desel_obj(tree, DOODSOK);
  585.                return ((WORD) *name);
  586.        }
  587.        else
  588.        {
  589.                desel_obj(tree, DOODSCNL);
  590.                return (FALSE);
  591.        }
  592. }
  593.  
  594.  
  595. /*------------------------------*/
  596. /*      get_path                */
  597. /*------------------------------*/
  598. VOID
  599. get_path(tmp_path, spec)        /* get directory path name      */
  600. BYTE    *tmp_path, *spec;
  601. {
  602.         WORD    cur_drv;
  603.  
  604.         cur_drv = Dgetdrv();
  605.         tmp_path[0] = cur_drv + 'A';
  606.         tmp_path[1] = ':';
  607.         tmp_path[2] = '\\';
  608.         Dgetpath(ADDR(&tmp_path[3]), cur_drv+1);
  609.         if (strlen(tmp_path) > 3)
  610.                 strcat(tmp_path, "\\");
  611.         else
  612.                 tmp_path[2] = '\0';
  613.         strcat(tmp_path, spec);
  614. }
  615.  
  616.  
  617. /*------------------------------*/
  618. /*      add_file_name           */
  619. /*------------------------------*/
  620. VOID
  621. add_file_name(dname, fname)     /* replace name at end of input file spec*/
  622. BYTE    *dname, *fname;
  623. {
  624.         BYTE    c;
  625.         WORD    ii;
  626.  
  627.  
  628.         ii = strlen(dname);
  629.         while (ii && (((c = dname[ii-1])  != '\\') && (c != ':')))
  630.                 ii--;
  631.         dname[ii] = '\0';
  632.         strcat(dname, fname);
  633. }
  634.  
  635.  
  636. /*------------------------------*/
  637. /*      get_file                */
  638. /*------------------------------*/
  639. WORD
  640. get_file(loop)                  /* use file selector to get input file  */
  641. BOOLEAN loop;
  642. {
  643.         WORD    fs_iexbutton;
  644.         BYTE    fs_iinsel[13];
  645.  
  646.         while (TRUE)
  647.         {
  648.                 get_path(file_name, "*.DOO");
  649.                 fs_iinsel[0] = '\0';
  650.  
  651.                 fsel_input(ADDR(file_name), ADDR(fs_iinsel), &fs_iexbutton);
  652.                 if (fs_iexbutton)
  653.                 {
  654.                         add_file_name(file_name, fs_iinsel);
  655.                         file_handle = Fopen(ADDR(file_name),2);
  656.                         dos_err = (file_handle < 0) ? -1 : 0;
  657.                         if (!loop || (loop && !dos_err))
  658.                                 return(1);
  659.                 }
  660.                 else
  661.                         return (0);
  662.         }
  663. } /* get_file */
  664.  
  665.  
  666. /*
  667.  
  668. Page*/
  669. /************************************************************************/
  670. /************************************************************************/
  671. /****                                                                ****/
  672. /****                       Soft Cursor Support                      ****/
  673. /****                                                                ****/
  674. /************************************************************************/
  675. /************************************************************************/
  676.  
  677.  
  678. /*------------------------------*/
  679. /*      cursor                  */
  680. /*------------------------------*/
  681. VOID
  682. cursor(color)                   /* turn cursor on,  color = pen_ink     */
  683. WORD    color;                  /*   or cursor off, color = bkgr_color  */
  684. {
  685.         WORD    pxy[4];
  686.  
  687.         pxy[0] = key_xcurr + 1;
  688.         pxy[1] = key_ycurr + gl_hspace;
  689.         pxy[2] = key_xcurr + 1;
  690.         pxy[3] = key_ycurr - gl_hbox;
  691.  
  692.         vsl_color(vdi_handle,color);
  693.         vswr_mode(vdi_handle,MD_REPLACE);
  694.         vsl_type (vdi_handle,IP_1PATT);
  695.         vsl_width (vdi_handle,PEN_FINE);
  696.         v_pline(vdi_handle, 2, pxy);
  697. }
  698.  
  699.  
  700. /*------------------------------*/
  701. /*      curs_on                 */
  702. /*------------------------------*/
  703. VOID
  704. curs_on()                       /* turn 'soft' cursor 'on'      */
  705. {
  706.         cursor(pen_ink);
  707. }
  708.  
  709. /*------------------------------*/
  710. /*      curs_off                */
  711. /*------------------------------*/
  712. VOID
  713. curs_off()                      /* turn 'soft' cursor 'off'     */
  714. {
  715.         cursor(bkgr_color);
  716. }
  717.  
  718.  
  719. /*
  720.  
  721. Page*/
  722. /************************************************************************/
  723. /************************************************************************/
  724. /****                                                                ****/
  725. /****                       Menu Handling                            ****/
  726. /****                                                                ****/
  727. /************************************************************************/
  728. /************************************************************************/
  729.  
  730.  
  731. /*------------------------------*/
  732. /*      hdl_menu                */
  733. /*------------------------------*/
  734. WORD
  735. hdl_menu(title, item)
  736. WORD    title, item;
  737. {
  738.         WORD    done;
  739.         WORD    me_creturn;
  740.  
  741.         graf_mouse(ARROW, 0x0L);
  742.         done = FALSE;
  743.         switch (title) {
  744.         case DOODDESK:
  745.                 if (item == DOODINFO)
  746.                         do_about();
  747.                 break;
  748.  
  749.         case DOODFILE:
  750.                 switch (item)
  751.                 {
  752.                 case DOODLOAD:
  753.                         do_load(TRUE);
  754.                         break;
  755.                 case DOODSAVE:
  756.                         do_sav();
  757.                         break;
  758.                 case DOODSVAS:
  759.                         do_savas();
  760.                         break;
  761.                 case DOODABAN:
  762.                         file_handle = Fopen(ADDR(file_name),2);
  763.                         do_load(FALSE);
  764.                         break;
  765.                 case DOODQUIT:
  766.                         done = TRUE;
  767.                         break;
  768.                 }
  769.  
  770.         case DOODOPTS:
  771.                 switch (item)
  772.                 {
  773.                 case DOODPENS:
  774.                         do_penselect();
  775.                         break;
  776.                 case DOODERAP:
  777.                         do_erase();
  778.                         first_fill = TRUE;
  779.                         break;
  780.                 }
  781.  
  782.         case DOODCOLR:
  783.                 switch (item)
  784.                 {
  785.                 case COLOR0:
  786.                         pen_ink = SHADE0;
  787.                         do_clnormal();
  788.                         me_creturn = menu_icheck (gl_menu, COLOR0, SELECTED);
  789.                         break;
  790.                 case COLOR1:
  791.                         pen_ink = SHADE1;
  792.                         do_clnormal();
  793.                         me_creturn = menu_icheck (gl_menu, COLOR1, SELECTED);
  794.                         break;
  795.                 case COLOR2:
  796.                         pen_ink = SHADE2;
  797.                         do_clnormal();
  798.                         me_creturn = menu_icheck (gl_menu, COLOR2, SELECTED);
  799.                         break;
  800.                 case COLOR3:
  801.                         pen_ink = SHADE3;
  802.                         do_clnormal();
  803.                         me_creturn = menu_icheck (gl_menu, COLOR3, SELECTED);
  804.                         break;
  805.                 case COLOR4:
  806.                         pen_ink = SHADE4;
  807.                         do_clnormal();
  808.                         me_creturn = menu_icheck (gl_menu, COLOR4, SELECTED);
  809.                         break;
  810.                 case COLOR5:
  811.                         pen_ink = SHADE5;
  812.                         do_clnormal();
  813.                         me_creturn = menu_icheck (gl_menu, COLOR5, SELECTED);
  814.                         break;
  815.                 case COLOR6:
  816.                         pen_ink = SHADE6;
  817.                         do_clnormal();
  818.                         me_creturn = menu_icheck (gl_menu, COLOR6, SELECTED);
  819.                         break;
  820.                 case COLOR7:
  821.                         pen_ink = SHADE7;
  822.                         do_clnormal();
  823.                         me_creturn = menu_icheck (gl_menu, COLOR7, SELECTED);
  824.                         break;
  825.                 case COLOR8:
  826.                         pen_ink = SHADE8;
  827.                         do_clnormal();
  828.                         me_creturn = menu_icheck (gl_menu, COLOR8, SELECTED);
  829.                         break;
  830.                 case COLOR9:
  831.                         pen_ink = SHADE9;
  832.                         do_clnormal();
  833.                         me_creturn = menu_icheck (gl_menu, COLOR9, SELECTED);
  834.                         break;
  835.                 case COLOR10:
  836.                         pen_ink = SHADE10;
  837.                         do_clnormal();
  838.                         me_creturn = menu_icheck (gl_menu, COLOR10, SELECTED);
  839.                         break;
  840.                 case COLOR11:
  841.                         pen_ink = SHADE11;
  842.                         do_clnormal();
  843.                         me_creturn = menu_icheck (gl_menu, COLOR11, SELECTED);
  844.                         break;
  845.                 case COLOR12:
  846.                         pen_ink = SHADE12;
  847.                         do_clnormal();
  848.                         me_creturn = menu_icheck (gl_menu, COLOR12, SELECTED);
  849.                         break;
  850.                 case COLOR13:
  851.                         pen_ink = SHADE13;
  852.                         do_clnormal();
  853.                         me_creturn = menu_icheck (gl_menu, COLOR13, SELECTED);
  854.                         break;
  855.                 case COLOR14:
  856.                         pen_ink = SHADE14;
  857.                         do_clnormal();
  858.                         me_creturn = menu_icheck (gl_menu, COLOR14, SELECTED);
  859.                         break;
  860.                 case COLOR15:
  861.                         pen_ink = SHADE15;
  862.                         do_clnormal();
  863.                         me_creturn = menu_icheck (gl_menu, COLOR15, SELECTED);
  864.                         break;
  865.                 }
  866.  
  867.                 dodle_shade = pen_ink;
  868.  
  869.         }
  870.         menu_tnormal(gl_menu,title,TRUE);
  871.         graf_mouse(monumber, mofaddr);
  872.         return (done);
  873. }
  874.  
  875.  
  876. /*------------------------------*/
  877. /*      do_clnormal             */
  878. /*------------------------------*/
  879. VOID
  880. do_clnormal()   /*      set all color checks to NORMAL in color menu    */
  881. {
  882.         WORD    me_creturn;
  883.  
  884.         me_creturn = menu_icheck(gl_menu, COLOR0, NORMAL);
  885.         me_creturn = menu_icheck(gl_menu, COLOR1, NORMAL);
  886.         me_creturn = menu_icheck(gl_menu, COLOR2, NORMAL);
  887.         me_creturn = menu_icheck(gl_menu, COLOR3, NORMAL);
  888.         me_creturn = menu_icheck(gl_menu, COLOR4, NORMAL);
  889.         me_creturn = menu_icheck(gl_menu, COLOR5, NORMAL);
  890.         me_creturn = menu_icheck(gl_menu, COLOR6, NORMAL);
  891.         me_creturn = menu_icheck(gl_menu, COLOR7, NORMAL);
  892.         me_creturn = menu_icheck(gl_menu, COLOR8, NORMAL);
  893.         me_creturn = menu_icheck(gl_menu, COLOR9, NORMAL);
  894.         me_creturn = menu_icheck(gl_menu, COLOR10, NORMAL);
  895.         me_creturn = menu_icheck(gl_menu, COLOR11, NORMAL);
  896.         me_creturn = menu_icheck(gl_menu, COLOR12, NORMAL);
  897.         me_creturn = menu_icheck(gl_menu, COLOR13, NORMAL);
  898.         me_creturn = menu_icheck(gl_menu, COLOR14, NORMAL);
  899.         me_creturn = menu_icheck(gl_menu, COLOR15, NORMAL);
  900. }
  901.  
  902. /*------------------------------*/
  903. /*      do_about                */
  904. /*------------------------------*/
  905. VOID
  906. do_about()                      /* display Doodle Info...       */
  907. {
  908.         LONG    tree;
  909.         GRECT   box;
  910.  
  911.         objc_xywh(gl_menu, DOODDESK, &box);
  912.         rsrc_gaddr(R_TREE, DOODINFD, &tree);
  913.         hndl_dial(tree, 0, box.g_x, box.g_y, box.g_w, box.g_h);
  914.         desel_obj(tree, DOODOK);
  915. }
  916.  
  917.  
  918. /*------------------------------*/
  919. /*      do_load                 */
  920. /*------------------------------*/
  921. VOID
  922. do_load(need_name)              /* load doodle picture file     */
  923. BOOLEAN need_name;
  924. {
  925.         if (!need_name || get_file(TRUE))
  926.         {
  927.                 if (!dos_err)
  928.                 {
  929.                         Fread(file_handle, buff_size,buff_location);
  930.                         Fclose(file_handle);
  931.                         enab_menu(DOODSAVE);
  932.                         enab_menu(DOODABAN);
  933.                         restore_work();
  934.                 }
  935.         }
  936. }
  937.  
  938.  
  939. /*------------------------------*/
  940. /*      do_sav                  */
  941. /*------------------------------*/
  942. VOID
  943. do_sav()                        /* save current named doodle picture    */
  944. {
  945.         if (*file_name)
  946.         {
  947.                 file_handle = Fopen(ADDR(file_name),2);
  948.                 dos_err = (file_handle < 0) ? 1 : 0;
  949.                 if (dos_err)
  950.                         file_handle = Fcreate(ADDR(file_name),0);
  951.                 else
  952.                 {
  953.                         if (form_alert(1, string_addr(DOODOVWR)) == 2)
  954.                                 return;
  955.                 }
  956.                 Fwrite(file_handle, buff_size, buff_location);
  957.                 enab_menu(DOODSAVE);
  958.                 enab_menu(DOODABAN);
  959.                 Fclose(file_handle);
  960.         }
  961. }
  962.  
  963.  
  964. /*------------------------------*/
  965. /*      do_sav_as               */
  966. /*------------------------------*/
  967. VOID
  968. do_savas()                      /* save doodle picture as named */
  969. {
  970.         BYTE    name[13];
  971.  
  972.         if (dial_name(&name[0]))
  973.         {
  974.                 add_file_name(file_name, name);
  975.                 do_sav();
  976.         }
  977. }
  978.  
  979.  
  980. /*------------------------------*/
  981. /*      do_penselect            */
  982. /*------------------------------*/
  983. VOID
  984. do_penselect()                  /* use dialogue box to input selection  */
  985. {                               /*   of specified pen/eraser            */
  986.         WORD    exit_obj;
  987.         LONG    tree;
  988.         GRECT   box;
  989.  
  990.         objc_xywh(gl_menu, DOODPENS, &box);
  991.         rsrc_gaddr(R_TREE, DOODPEND, &tree);
  992.         /**/                    /* first setup current selection state  */
  993.         if (dodle_pen == PEN_FINE)
  994.         {
  995.                 sel_obj(tree, DOODFINE);
  996.                 desel_obj(tree, DOODMED);
  997.                 desel_obj(tree, DOODBRD);
  998.         }
  999.         else
  1000.                 if (dodle_pen == PEN_MEDIUM)
  1001.                 {
  1002.                         sel_obj(tree, DOODMED);
  1003.                         desel_obj(tree, DOODFINE);
  1004.                         desel_obj(tree, DOODBRD);
  1005.                 }
  1006.                 else
  1007.                 {
  1008.                         sel_obj(tree, DOODBRD);
  1009.                         desel_obj(tree, DOODFINE);
  1010.                         desel_obj(tree, DOODMED);
  1011.                 }
  1012.         if (dodle_shade == pen_ink && dood_fill == FALSE)
  1013.         {
  1014.                 sel_obj(tree, DOODPEN);
  1015.                 desel_obj(tree, DOODERSR);
  1016.                 desel_obj(tree, DOODFILL);
  1017.         }
  1018.         else if (dodle_shade == pen_ink && dood_fill == TRUE)
  1019.         {
  1020.                 desel_obj(tree, DOODPEN);
  1021.                 desel_obj(tree, DOODERSR);
  1022.                 sel_obj(tree, DOODFILL);
  1023.         }
  1024.         else
  1025.         {
  1026.                 desel_obj(tree, DOODPEN);
  1027.                 sel_obj(tree, DOODERSR);
  1028.                 desel_obj(tree, DOODFILL);
  1029.         }
  1030.  
  1031.         /* get dialogue box input       */
  1032.  
  1033.         exit_obj = hndl_dial(tree, 0, box.g_x, box.g_y, box.g_w, box.g_h);
  1034.         if (exit_obj == DOODPSOK)
  1035.         {
  1036.                 if (LWGET(OB_STATE(DOODFINE)) & SELECTED)
  1037.                 {
  1038.                         dodle_pen = PEN_FINE;
  1039.                         dodle_height = char_fine;
  1040.                 }
  1041.                 else
  1042.                         if (LWGET(OB_STATE(DOODMED)) & SELECTED)
  1043.                         {
  1044.                                 dodle_pen = PEN_MEDIUM;
  1045.                                 dodle_height = char_medium;
  1046.                         }
  1047.                         else
  1048.                         {
  1049.                                 dodle_pen = PEN_BROAD;
  1050.                                 dodle_height = char_broad;
  1051.                         }
  1052.                 if (LWGET(OB_STATE(DOODPEN)) & SELECTED)
  1053.                 {
  1054.                         dodle_shade = pen_ink;
  1055.                         monumber = 5;
  1056.                         mofaddr = 0x0L;
  1057.                         dood_fill = FALSE;
  1058.                 }
  1059.                 else if (LWGET(OB_STATE(DOODERSR)) & SELECTED)
  1060.                 {
  1061.                    dodle_shade = bkgr_color;
  1062.                    monumber = 255;
  1063.                    mofaddr=(dodle_pen==PEN_FINE) ? ADDR((BYTE *)erase_fine):
  1064.                    (dodle_pen == PEN_MEDIUM) ? ADDR((BYTE *)erase_medium) :
  1065.                    ADDR((BYTE *)erase_broad);
  1066.                    dood_fill = FALSE;
  1067.                 }
  1068.                 else
  1069.                 {
  1070.                         dodle_shade = pen_ink;
  1071.                         monumber = POINT_HAND;
  1072.                         mofaddr = 0x0L;
  1073.                         dood_fill = TRUE;
  1074.                 }
  1075.  
  1076.                 desel_obj(tree, DOODPSOK);
  1077.         }
  1078.         else
  1079.                 desel_obj(tree, DOODCNCL);
  1080. }
  1081.  
  1082.  
  1083. /*------------------------------*/
  1084. /*      do_erase                */
  1085. /*------------------------------*/
  1086. VOID
  1087. do_erase()                      /* clear the scrn and the undo buffer   */
  1088. {
  1089.         WORD    fo_aexbttn;
  1090.  
  1091.         fo_aexbttn = form_alert(0, string_addr(ERASEWRN));
  1092.  
  1093.         if (fo_aexbttn == 1)
  1094.         {
  1095.                 rast_op(0, &scrn_area, &scrn_mfdb, &scrn_area, &undo_mfdb);
  1096.                 restore_work();
  1097.         }
  1098. }
  1099. /*
  1100.  
  1101. Page*/
  1102. /************************************************************************/
  1103. /************************************************************************/
  1104. /****                                                                ****/
  1105. /****                       Keyboard Handling                        ****/
  1106. /****                                                                ****/
  1107. /************************************************************************/
  1108. /************************************************************************/
  1109.  
  1110.  
  1111. /*------------------------------*/
  1112. /*      hndl_keyboard           */
  1113. /*------------------------------*/
  1114. WORD
  1115. hndl_keyboard()
  1116. {
  1117.         WORD    i;
  1118.         BYTE    str[2];
  1119.  
  1120.         if ((str[0] = kreturn) == 0x03)
  1121.                 return(TRUE);
  1122.         graf_mouse(M_OFF, 0x0L);
  1123.         if (!key_input)
  1124.         {
  1125.                 vsl_color(vdi_handle,dodle_shade);
  1126.                 vswr_mode(vdi_handle,MD_TRANS);
  1127.                 vsl_type (vdi_handle,IP_1PATT);
  1128.                 vst_height(vdi_handle, dodle_height,
  1129.                 &gl_wchar,&gl_hchar,&gl_wbox,&gl_hbox);
  1130.                 gl_hspace = gl_hbox - gl_hchar;
  1131.                 set_clip(TRUE, &work_area);
  1132.                 graf_mkstate(&key_xbeg, &key_ybeg, &i, &i);
  1133.                 key_xcurr = ++key_xbeg;
  1134.                 key_ycurr = --key_ybeg;
  1135.         }
  1136.         else
  1137.  
  1138.         /*      curs_off();     remove from color version 6/30/85       */
  1139.  
  1140.         str[1] = '\0';
  1141.         if (str[0] == 0x1A)
  1142.         {
  1143.                 save_work();
  1144.                 graf_mouse(M_ON, 0x0L);
  1145.                 return(key_input = FALSE);
  1146.         }
  1147.         else
  1148.                 if (str[0] == 0x0D)
  1149.                 {
  1150.                         key_ycurr += gl_hbox + gl_hspace;
  1151.                         key_xcurr = key_xbeg;
  1152.                 }
  1153.                 else
  1154.                         if (str[0] == 0x08)
  1155.                         {
  1156.                                 if (key_input && (key_xcurr != key_xbeg))
  1157.                                 {
  1158.                                         for (i = 0; i < gl_wbox; i++)
  1159.                                         {
  1160.                                                 key_xcurr--;
  1161.                                         /*      curs_off();     */
  1162.                                         }
  1163.                                 }
  1164.                         }
  1165.                         else
  1166.                                 if ((str[0] >= ' ') && (str[0] <= 'z'))
  1167.                                 {
  1168.                                         str[1] = '\0';
  1169.                                         vswr_mode(vdi_handle, MD_TRANS);
  1170.                                         vst_color(vdi_handle, pen_ink);
  1171.                                         v_gtext(vdi_handle, key_xcurr,
  1172.                                         key_ycurr, str);
  1173.                                         key_xcurr += gl_wbox;
  1174.                                 }
  1175.         if (!key_input)
  1176.         {
  1177.                 key_input = TRUE;
  1178.         }
  1179.         /*      curs_on();      remove from color version 6/30/85  */
  1180.         graf_mouse(M_ON, 0x0L);
  1181.         return(FALSE);
  1182. }
  1183. /****                       Message Handling                         ****/
  1184. /*      hndl_msg      *****************************************//*MLOCAL*/
  1185. BOOLEAN hndl_msg()
  1186. {
  1187.         BOOLEAN done; 
  1188.         WORD    wdw_hndl;
  1189.  
  1190.         done = FALSE;
  1191.         wdw_hndl = gl_rmsg[3];
  1192.         switch( gl_rmsg[0] )
  1193.         {
  1194.         case MN_SELECTED:
  1195.                 done = hdl_menu(wdw_hndl, gl_rmsg[4]);
  1196.                 break;
  1197.  
  1198.         case WM_REDRAW:
  1199.                 do_redraw(wdw_hndl, (GRECT *) &gl_rmsg[4]);
  1200.                 break;
  1201.  
  1202.         case WM_TOPPED:
  1203.                 wind_set(wdw_hndl, WF_TOP, 0, 0, 0, 0);
  1204.                 break;
  1205.         case WM_CLOSED:
  1206.                 done = TRUE;
  1207.                 break;
  1208.         case WM_FULLED:
  1209.                 do_full(wdw_hndl);
  1210.                 break;
  1211.         case WM_ARROWED:
  1212.                 switch(gl_rmsg[4])
  1213.                 {
  1214.                 case WA_UPPAGE:
  1215.                         undo_area.g_y = max(undo_area.g_y - undo_area.g_h, 0);
  1216.                         break;
  1217.                 case WA_DNPAGE:
  1218.                         undo_area.g_y += undo_area.g_h;
  1219.                         break;
  1220.                 case WA_UPLINE:
  1221.                         undo_area.g_y = max(undo_area.g_y - YSCALE(16), 0);
  1222.                         break;
  1223.                 case WA_DNLINE:
  1224.                         undo_area.g_y += YSCALE(16);
  1225.                         break;
  1226.                 case WA_LFPAGE:
  1227.                         undo_area.g_x = max(undo_area.g_x-undo_area.g_w, 0);
  1228.                         break;
  1229.                 case WA_RTPAGE:
  1230.                         undo_area.g_x += undo_area.g_w;
  1231.                         break;
  1232.                 case WA_LFLINE:
  1233.                         undo_area.g_x = max(undo_area.g_x - 16, 0);
  1234.                         break;
  1235.                 case WA_RTLINE:
  1236.                         undo_area.g_x += 16;
  1237.                         break;
  1238.                 }
  1239.                 set_work(TRUE);
  1240.                 restore_work();
  1241.                 break;
  1242.         case WM_HSLID:
  1243.                 undo_area.g_x = align_x(UMD(undo_mfdb.fwp - undo_area.g_w,
  1244.                 gl_rmsg[4], 1000));
  1245.                 wind_set(dodle_whndl, WF_HSLIDE, UMD(undo_area.g_x, 1000,
  1246.                 undo_mfdb.fwp - undo_area.g_w), 0, 0, 0);
  1247.                 restore_work();
  1248.                 break;
  1249.         case WM_VSLID:
  1250.                 undo_area.g_y = UMD(undo_mfdb.fh - undo_area.g_h,
  1251.                 gl_rmsg[4],1000);
  1252.                 wind_set(dodle_whndl, WF_VSLIDE, UMD(undo_area.g_y, 1000,
  1253.                 undo_mfdb.fh - undo_area.g_h), 0, 0, 0);
  1254.                 restore_work();
  1255.                 break;
  1256.         case WM_SIZED:
  1257.                 wind_set(wdw_hndl, WF_CURRXYWH, align_x(gl_rmsg[4]) - 1,
  1258.                 gl_rmsg[5], gl_rmsg[6], gl_rmsg[7]);
  1259.                 set_work(TRUE);
  1260.                 break;
  1261.         case WM_MOVED:
  1262.                 gl_rmsg[4] = align_x(gl_rmsg[4]);
  1263.                 wind_set(wdw_hndl, WF_CURRXYWH, align_x(gl_rmsg[4]) - 1,
  1264.                 gl_rmsg[5], gl_rmsg[6], gl_rmsg[7]);
  1265.                 set_work(FALSE);
  1266.                 break;
  1267.         } /* switch */
  1268.         return(done);
  1269. } /* hndl_msg */
  1270.  
  1271. /*------------------------------*/
  1272. /*      do_redraw               */
  1273. /*------------------------------*/
  1274. VOID
  1275. do_redraw(wh, area)             /* redraw specified area from undo bfr  */
  1276. WORD    wh;
  1277. GRECT   *area;
  1278. {
  1279.         GRECT   box;
  1280.         GRECT   dirty_source, dirty_dest;
  1281.  
  1282.         graf_mouse(M_OFF, 0x0L);
  1283.  
  1284.         wind_get(wh, WF_FIRSTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  1285.         while ( box.g_w && box.g_h )
  1286.         {
  1287.                 if (rc_intersect(area, &box))
  1288.                 {
  1289.                         if (wh == dodle_whndl)
  1290.                         {
  1291.                             rc_copy(&box, &dirty_dest);
  1292.                             if (rc_intersect(&work_area, &dirty_dest))
  1293.                             {
  1294.                                dirty_source.g_x = (dirty_dest.g_x
  1295.                                           - work_area.g_x)  + undo_area.g_x;
  1296.                                dirty_source.g_y = (dirty_dest.g_y
  1297.                                           - work_area.g_y)  + undo_area.g_y;
  1298.                                dirty_source.g_w = dirty_dest.g_w;
  1299.                                dirty_source.g_h = dirty_dest.g_h;
  1300.                                rast_op(3, &dirty_source, &undo_mfdb,
  1301.                                     &dirty_dest, &scrn_mfdb);
  1302.                                 }
  1303.                         }
  1304.                 }
  1305.             wind_get(wh, WF_NEXTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  1306.         }
  1307.         graf_mouse(M_ON, 0x0L);
  1308. }
  1309.  
  1310. /*------------------------------*/
  1311. /*      do_full                 */
  1312. /*------------------------------*/
  1313. VOID
  1314. do_full(wh)     /* depending on current window state, either make window*/
  1315. WORD    wh;     /*   full size -or- return to previous shrunken size    */
  1316. {
  1317.         GRECT   prev;
  1318.         GRECT   curr;
  1319.         GRECT   full;
  1320.  
  1321.         graf_mouse(M_OFF,0x0L);
  1322.         wind_get(wh, WF_CURRXYWH, &curr.g_x, &curr.g_y, &curr.g_w, &curr.g_h);
  1323.         wind_get(wh, WF_PREVXYWH, &prev.g_x, &prev.g_y, &prev.g_w, &prev.g_h);
  1324.         wind_get(wh, WF_FULLXYWH, &full.g_x, &full.g_y, &full.g_w, &full.g_h);
  1325.         if ( rc_equal(&curr, &full) )
  1326.         {                                       /* is full now so change*/
  1327.            /**/                                    /*   to previous     */
  1328.            graf_shrinkbox(prev.g_x, prev.g_y, prev.g_w, prev.g_h,
  1329.                         full.g_x, full.g_y, full.g_w, full.g_h);
  1330.            wind_set(wh,WF_CURRXYWH,prev.g_x,prev.g_y,prev.g_w,prev.g_h);
  1331.            rc_copy(&save_area, &undo_area);
  1332.            set_work(TRUE);
  1333.            if ((prev.g_x == full.g_x) && (prev.g_y == full.g_y))
  1334.                         do_redraw(wh, &work_area);
  1335.         }
  1336.         else
  1337.         {                                       /* is not full so make  */
  1338.            /**/                                    /*   it full         */
  1339.            rc_copy(&undo_area, &save_area);
  1340.            graf_growbox(curr.g_x, curr.g_y, curr.g_w, curr.g_h,
  1341.                         full.g_x, full.g_y, full.g_w, full.g_h);
  1342.            wind_set(wh, WF_CURRXYWH, full.g_x, full.g_y, full.g_w, full.g_h);
  1343.            set_work(TRUE);
  1344.         }
  1345.         graf_mouse(M_ON,0x0L);
  1346. }
  1347. /****                       Mouse Handling                           ****/
  1348. /*      hdl_mouse               */
  1349. WORD    hdl_mouse()
  1350. {
  1351.         BOOLEAN done;
  1352.  
  1353.         if (m_out)
  1354.                 graf_mouse(ARROW, 0x0L);
  1355.         else
  1356.                 graf_mouse(monumber, mofaddr);
  1357.  
  1358.         m_out = !m_out;
  1359.         done = FALSE;
  1360.         return(done);
  1361. }
  1362. /****                       Button Handling                          ****/
  1363. /*      hndl_button             */
  1364. WORD    hndl_button()
  1365. {
  1366.         WORD    done;
  1367.  
  1368.         done = FALSE;
  1369.         if (inside(mousex, mousey, &work_area))
  1370.         {
  1371.                 if (dood_fill == TRUE)
  1372.                         do_fill(mousex, mousey);
  1373.                 else
  1374.                         draw_pencil(mousex, mousey);
  1375.         }
  1376.         return(done);
  1377. }
  1378.  
  1379.  
  1380. /*------------------------------*/
  1381. /*      draw_pencil             */
  1382. /*------------------------------*/
  1383. WORD
  1384. draw_pencil(x, y)
  1385. UWORD   x, y;
  1386. {
  1387.         UWORD   pxy[4];
  1388.         WORD    done;
  1389.         UWORD   mflags;
  1390.         UWORD   locount, hicount;
  1391.         UWORD   ev_which, bbutton, kstate, kreturn, breturn;
  1392.  
  1393.         set_clip(TRUE, &work_area);
  1394.         pxy[0] = x;
  1395.         pxy[1] = y;
  1396.  
  1397.         vsl_color(vdi_handle,dodle_shade);
  1398.         vswr_mode(vdi_handle,MD_REPLACE);
  1399.         vsl_type (vdi_handle,IP_1PATT);
  1400.  
  1401.         if (dodle_shade == pen_ink)
  1402.         {
  1403.                 vsl_width (vdi_handle,dodle_pen);
  1404.                 vsl_ends(vdi_handle, 2, 2);
  1405.                 hicount = 0;
  1406.                 locount = 125;
  1407.                 mflags = MU_BUTTON | MU_M1 | MU_TIMER;
  1408.                 graf_mouse(M_OFF, 0x0L);
  1409.         }
  1410.         else
  1411.         {
  1412.                 vsf_interior(vdi_handle, 1);
  1413.                 vsf_color(vdi_handle, bkgr_color);
  1414.                 mflags = MU_BUTTON | MU_M1;
  1415.         }
  1416.  
  1417.         done = FALSE;
  1418.         while (!done)
  1419.         {
  1420.                 ev_which = evnt_multi(mflags,
  1421.                 0x01, 0x01, 0x00, 
  1422.                 1, pxy[0], pxy[1], 1, 1,
  1423.                 0, 0, 0, 0, 0,
  1424.                 ad_rmsg, locount, hicount,
  1425.                 &pxy[2], &pxy[3], &bbutton, &kstate,
  1426.                 &kreturn, &breturn);
  1427.  
  1428.                 if (ev_which & MU_BUTTON)
  1429.                 {
  1430.                         if (!(mflags & MU_TIMER))
  1431.                                 graf_mouse(M_OFF, 0x0L);
  1432.                         if (dodle_shade == pen_ink)
  1433.                                 v_pline(vdi_handle, 2, (WORD *) pxy);
  1434.                         else
  1435.                                 eraser((WORD) pxy[2], (WORD) pxy[3]);
  1436.                         graf_mouse(M_ON, 0x0L);
  1437.                         done = TRUE;
  1438.                 }
  1439.                 else
  1440.                         if (ev_which & MU_TIMER)
  1441.                         {
  1442.                                 graf_mouse(M_ON, 0x0L);
  1443.                                 mflags = MU_BUTTON | MU_M1;
  1444.                         }
  1445.                         else
  1446.                         {
  1447.                                 if (!(mflags & MU_TIMER))
  1448.                                         graf_mouse(M_OFF, 0x0L);
  1449.                                 if (dodle_shade == pen_ink)
  1450.                                 {
  1451.                                         v_pline(vdi_handle, 2, (WORD *) pxy);
  1452.                                         mflags = MU_BUTTON | MU_M1 | MU_TIMER;
  1453.                                 }
  1454.                                 else
  1455.                                 {
  1456.                                         eraser((WORD) pxy[2], (WORD) pxy[3]);
  1457.                                         graf_mouse(M_ON,0x0L);
  1458.                                 }
  1459.                                 pxy[0] = pxy[2];
  1460.                                 pxy[1] = pxy[3];
  1461.                         }
  1462.         } /* while */
  1463.  
  1464.         set_clip(FALSE, &work_area);
  1465.         save_work();
  1466. }
  1467.  
  1468.  
  1469. /*------------------------------*/
  1470. /*      eraser                  */
  1471. /*------------------------------*/
  1472. VOID
  1473. eraser(x, y)                    /* erase rectangle of eraser size at x,y */
  1474. WORD    x, y;
  1475. {
  1476.         WORD    erase_xy[4];
  1477.  
  1478.         if (dodle_pen == PEN_FINE)
  1479.         {
  1480.                 erase_xy[0] = x - 2;
  1481.                 erase_xy[1] = y - 1;
  1482.                 erase_xy[2] = x + 2;
  1483.                 erase_xy[3] = y + 1;
  1484.         }
  1485.         else
  1486.                 if (dodle_pen == PEN_MEDIUM)
  1487.                 {
  1488.                         erase_xy[0] = x - 4;
  1489.                         erase_xy[1] = y - 2;
  1490.                         erase_xy[2] = x + 4;
  1491.                         erase_xy[3] = y + 2;
  1492.                 }
  1493.                 else
  1494.                 {
  1495.                         erase_xy[0] = x - 6;
  1496.                         erase_xy[1] = y - 3;
  1497.                         erase_xy[2] = x + 6;
  1498.                         erase_xy[3] = y + 3;
  1499.                 }
  1500.         vr_recfl(vdi_handle, erase_xy);
  1501. }
  1502.  
  1503. /*----------------------------------------------*/
  1504. /*      do_fill         HK 6/30/85              */
  1505. /*----------------------------------------------*/
  1506. WORD
  1507. do_fill(x, y)
  1508. WORD x, y;
  1509. {
  1510.         WORD    index;
  1511.  
  1512.         vsf_interior(vdi_handle, IP_1PATT);
  1513.         vsf_color(vdi_handle, pen_ink);
  1514.         index = -1;     /* for complete fill */
  1515.  
  1516.         graf_mouse(M_OFF, 0x0L);
  1517.         v_contourfill(vdi_handle, x, y, index);
  1518.         save_work();
  1519.         graf_mouse(M_ON, 0x0L);
  1520.         
  1521.         if (first_fill == TRUE)
  1522.         {
  1523.                 bkgr_color = pen_ink;
  1524.                 first_fill = FALSE;
  1525.         }
  1526. }
  1527. /****                       Doodle Event Handler                     ****/
  1528. /*      dodle         ****************************************          */
  1529. VOID    dodle()
  1530. {
  1531.         BOOLEAN done;
  1532.  
  1533.         key_input = FALSE;
  1534.         done = FALSE;
  1535.         while( !done )          /* loop handling user input until done  */
  1536.         {
  1537.                 ev_which = evnt_multi(MU_BUTTON | MU_MESAG | MU_M1 | MU_KEYBD,
  1538.                 0x02, 0x01, 0x01, 
  1539.                 m_out,
  1540.                 (UWORD) work_area.g_x, (UWORD) work_area.g_y,
  1541.                 (UWORD) work_area.g_w, (UWORD) work_area.g_h,
  1542.                 0, 0, 0, 0, 0,
  1543.                 ad_rmsg, 0, 0, 
  1544.                 &mousex, &mousey, &bstate, &kstate,
  1545.                 &kreturn, &bclicks);
  1546.  
  1547.                 wind_update(BEG_UPDATE);
  1548.  
  1549.                 if (!(ev_which & MU_KEYBD))
  1550.                 {
  1551.                         if (key_input)
  1552.                         {
  1553. /*                              curs_off();     */
  1554.                                 key_input = FALSE;
  1555.                                 save_work();
  1556.                         }
  1557.                 }
  1558.  
  1559.                 if (ev_which & MU_BUTTON)
  1560.                         done = hndl_button();
  1561.  
  1562.                 if (ev_which & MU_M1)
  1563.                         done = hdl_mouse();
  1564.  
  1565.                 if (ev_which & MU_MESAG)
  1566.                         done = hndl_msg();
  1567.  
  1568.                 if (ev_which & MU_KEYBD)
  1569.                         done = hndl_keyboard();
  1570.  
  1571.                 wind_update(END_UPDATE);
  1572.         }
  1573. }
  1574. /*
  1575.  
  1576. Page*/
  1577. /************************************************************************/
  1578. /************************************************************************/
  1579. /****                                                                ****/
  1580. /****                       Termination                              ****/
  1581. /****                                                                ****/
  1582. /************************************************************************/
  1583. /************************************************************************/
  1584.  
  1585.  
  1586. /*------------------------------*/
  1587. /*      dodle_term              */
  1588. /*------------------------------*/
  1589. dodle_term(term_type)
  1590. WORD    term_type;
  1591. {
  1592.         switch (term_type)      /* NOTE: all cases fall through         */
  1593.         {
  1594.                 case (0 /* normal termination */):
  1595.                         do_close(dodle_whndl, gl_wfull/2, gl_hfull/2);
  1596.                         wind_delete(dodle_whndl);
  1597.                 case (3):
  1598.                         menu_bar(0x0L, FALSE);
  1599.                         Mfree(undo_mfdb.mp);
  1600.                 case (2):
  1601.                         v_clsvwk( vdi_handle );
  1602.                 case (1):
  1603.                         appl_exit();
  1604.                 case (4):
  1605.                         break;
  1606.         }
  1607. }
  1608. /****                       Initialization                           ****/
  1609. /*      dodle_init              */
  1610. WORD    dodle_init()
  1611. {
  1612.         WORD    work_in[11];
  1613.         WORD    i;
  1614.         WORD    me_creturn;
  1615.         gl_apid = appl_init();                  /* initialize libraries */
  1616.         if (gl_apid == -1)
  1617.                 return(4);
  1618.         wind_update(BEG_UPDATE);
  1619.         graf_mouse(HOURGLASS, 0x0L);
  1620.         if (!rsrc_load( ADDR("DOODLE2.RSC") ))
  1621.         {
  1622.                graf_mouse(ARROW, 0x0L);
  1623.                form_alert(1,
  1624.                ADDR("[3][Fatal Error !|DOODLE2.RSC|File Not Found][ Abort ]"));
  1625.                return(1);
  1626.         }
  1627.         /* open virtual workstation */
  1628.         /* allocate undo buffer */
  1629.         for (i=0; i<10; i++)
  1630.         {
  1631.                 work_in[i]=1;
  1632.         }
  1633.         work_in[10]=2;
  1634.  
  1635.         gem_handle = graf_handle(&gl_wchar,&gl_hchar,&gl_wbox,&gl_hbox);
  1636.         vdi_handle = gem_handle;
  1637.         v_opnvwk(work_in,&vdi_handle,work_out);
  1638.  
  1639.         if (vdi_handle == 0)
  1640.                 return(1);
  1641.  
  1642.         scrn_width = work_out[0] + 1;
  1643.         scrn_height = work_out[1] + 1;
  1644.         scrn_xsize = work_out[3];
  1645.         scrn_ysize = work_out[4];
  1646.  
  1647.         char_fine = work_out[46];
  1648.         char_medium = work_out[48];
  1649.         char_broad = char_medium * 2;
  1650.  
  1651.         vq_extnd(vdi_handle, 1, work_out);
  1652.         scrn_planes = work_out[4];
  1653.  
  1654.         undo_mfdb.fwp = scrn_width;
  1655.         undo_mfdb.fww = undo_mfdb.fwp>>4;
  1656.         undo_mfdb.fh = scrn_height;
  1657.         undo_mfdb.np = scrn_planes;
  1658.         undo_mfdb.ff = 0;
  1659.  
  1660.         buff_size = (LONG)(undo_mfdb.fwp>>3) *
  1661.             (LONG)undo_mfdb.fh *
  1662.             (LONG)undo_mfdb.np;
  1663.         buff_location =
  1664.             undo_mfdb.mp  = Malloc(buff_size);
  1665.         if (undo_mfdb.mp == 0)
  1666.                 return(2);
  1667.         scrn_area.g_x = 0;
  1668.         scrn_area.g_y = 0;
  1669.         scrn_area.g_w = scrn_width;
  1670.         scrn_area.g_h = scrn_height;
  1671.         scrn_mfdb.mp = 0x0L;
  1672.  
  1673.         rc_copy(&scrn_area, &undo_area);
  1674.         rast_op(0, &undo_area, &scrn_mfdb, &undo_area, &undo_mfdb);
  1675.  
  1676.         ad_rmsg = ADDR((BYTE *) &gl_rmsg[0]);
  1677.  
  1678.         wind_get(DESK, WF_WORKXYWH,&gl_xfull,&gl_yfull,&gl_wfull,&gl_hfull);
  1679.  
  1680.         /* initialize menu      */
  1681.         rsrc_gaddr(R_TREE, DOODMENU, &gl_menu);
  1682.         do_clnormal();
  1683.         me_creturn = menu_icheck (gl_menu, COLOR1, SELECTED);
  1684.  
  1685.         /* show menu            */
  1686.         menu_bar(gl_menu, TRUE);        
  1687.  
  1688.         dodle_whndl = wind_create(0x0fef, gl_xfull - 1, gl_yfull,
  1689.         gl_wfull, gl_hfull);
  1690.         if (dodle_whndl == -1)
  1691.         {
  1692.                 form_alert(1, string_addr(DOODNWDW));
  1693.                 return(3);
  1694.         }
  1695.  
  1696.         graf_mouse(HOURGLASS, 0x0L);
  1697.         wind_set(dodle_whndl, WF_NAME,
  1698.         " Dr. Doodle Window ", 0, 0);
  1699.         gl_xfull = align_x(gl_xfull);
  1700.         do_open(dodle_whndl, gl_wfull/2, gl_hfull/2, align_x(gl_xfull),
  1701.                 gl_yfull, gl_wfull, gl_hfull);
  1702.         wind_get(dodle_whndl, WF_WORKXYWH,
  1703.         &work_area.g_x, &work_area.g_y,
  1704.         &work_area.g_w, &work_area.g_h);
  1705.  
  1706.         set_work(TRUE);
  1707.         rc_copy (&undo_area, &save_area);
  1708.  
  1709.         graf_mouse(ARROW,0x0L);
  1710.         wind_update(END_UPDATE);
  1711.         return(0);
  1712. }
  1713. /****                       Main Program                             ****/
  1714. /*      main()                  */
  1715. WORD    main()
  1716. {
  1717.         WORD    term_type;
  1718.  
  1719.         if (!(term_type = dodle_init()))
  1720.                 dodle();
  1721.         dodle_term(term_type);
  1722. }
  1723.  
  1724. /*  FUNCTION     *********************************************************/
  1725. /* UMUL_DIV() I don't know who needs this in capitals letters but it won't
  1726.     UMD.......for easier typing.........     \  link without it otherwise*/
  1727. int UMD(m1, m2, d1)
  1728. unsigned int m1;
  1729. unsigned int m2;
  1730. unsigned int d1;
  1731. {
  1732.         unsigned int x;
  1733.         x = m2;
  1734.         x = x << 1;
  1735.         x *= m1;
  1736.         x /= d1;
  1737.         x += 1;
  1738.         x = x >> 1;
  1739.         return(x);
  1740. }
  1741.